<template>
  <div
    ref="containerRef"
    :style="{ userSelect: userSelect, gridTemplate: gridTemplate }"
    :class="['vue-splitter', { horizontal: isHorizontal, vertical: !isHorizontal }]"
  >
    <!-- 左或上窗格 -->
    <div v-if="hasTopOrLeftContent" :class="['splitter-pane', topOrLeftPaneClass]">
      <slot name="left-pane"></slot>
      <slot name="top-pane"></slot>
    </div>

    <!-- 分割线，只有当两边窗格都有内容时显示 -->
    <div
      v-if="hasTopOrLeftContent && hasBottomOrRightContent"
      class="splitter"
      :class="{ active: isResizing }"
      @mousedown="handleMouseDown"
      @touchstart.passive="handleTouchStart"
      @click="handleClick"
    ></div>

    <!-- 右或下窗格 -->
    <div v-if="hasBottomOrRightContent" :class="['splitter-pane', bottomOrRightPaneClass]">
      <slot name="right-pane"></slot>
      <slot name="bottom-pane"></slot>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted, watch, useSlots } from 'vue'
import { nextTick } from 'vue'

const key = ref(1)

const slots = useSlots()
const hasTopOrLeftContent = computed(() => {
  return slots['left-pane']?.() || slots['top-pane']?.()
})
const hasBottomOrRightContent = computed(() => {
  return slots['right-pane']?.() || slots['bottom-pane']?.()
})

// 从父组件传入的props
const props = defineProps({
  isHorizontal: Boolean,
  initialPercent: Number,
})

// 组件内部的响应式状态
const isHorizontal = ref(props.isHorizontal || false)
const percent = ref(props.initialPercent || 50)
const isResizing = ref(false)
const containerRef = ref(null)

// 计算属性，用于设置CSS样式
const topOrLeftPaneClass = computed(() => (isHorizontal.value ? 'top-pane' : 'left-pane'))
const bottomOrRightPaneClass = computed(() => (isHorizontal.value ? 'bottom-pane' : 'right-pane'))
const gridTemplate = computed(() =>
  isHorizontal.value ? `${percent.value}% auto 1fr / none` : `none / ${percent.value}% auto 1fr`,
)
const userSelect = computed(() => (isResizing.value ? 'none' : 'auto'))
// 监听props.initialPercent的变化
watch(
  () => props.initialPercent,
  (newPercent) => {
    percent.value = newPercent
  },
)

// 鼠标移动和抬起事件的处理逻辑
const handleMouseMove = (event) => {
  if (!isResizing.value) return
  const bounds = containerRef.value.getBoundingClientRect()
  let newPercent = 0
  if (isHorizontal.value) {
    newPercent = ((event.clientY - bounds.top) / bounds.height) * 100
  } else {
    newPercent = ((event.clientX - bounds.left) / bounds.width) * 100
  }
  percent.value = Math.max(0, Math.min(newPercent, 100))
}

const handleMouseUp = () => {
  if (!isResizing.value) return
  isResizing.value = false
  window.removeEventListener('mousemove', handleMouseMove)
  window.removeEventListener('mouseup', handleMouseUp)
}

// 开始调整大小的逻辑
const startResizing = (event) => {
  isResizing.value = true
  // 使用window对象来添加全局事件监听器
  window.addEventListener('mousemove', handleMouseMove)
  window.addEventListener('mouseup', handleMouseUp)
}

// 添加到容器元素的鼠标按下事件监听器
const initResizeListeners = () => {
  containerRef.value.addEventListener('mousedown', (event) => {
    // 只有点击分割条时才开始调整大小
    if (event.target === containerRef.value.querySelector('.splitter')) {
      startResizing(event)
    }
  })
}

// 组件挂载和卸载时的逻辑
onMounted(initResizeListeners)

onUnmounted(() => {
  if (containerRef.value) {
    containerRef.value.removeEventListener('mousedown', startResizing)
  }
  // 清理全局事件监听器
  window.removeEventListener('mousemove', handleMouseMove)
  window.removeEventListener('mouseup', handleMouseUp)
})
</script>

<style scoped>
.vue-splitter {
  display: grid;
  /* height: inherit; */
}

.vue-splitter.vertical {
  width: 100%;
}

.vue-splitter.vertical > .splitter {
  cursor: ew-resize;
  width: 5px; /* The fixed width of the splitter */
  background-color: white; /* The background color */
  position: relative; /* Required for positioning the inner line */
}
.vue-splitter.vertical > .splitter::before {
  content: '';
  position: absolute;
  left: 50%; /* Center the line horizontally */
  top: 0;
  bottom: 0;
  width: 1px; /* The width of the black line */
  background-color: gray; /* The color of the line */
  transform: translateX(-50%);
}

.vue-splitter.horizontal {
  height: 100%;
}

.vue-splitter.horizontal > .splitter {
  cursor: ns-resize;
  height: 5px; /* The fixed height of the splitter */
  background-color: white; /* The background color */
  position: relative; /* Required for positioning the inner line */
}

.vue-splitter.horizontal > .splitter::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 50%; /* Center the line vertically */
  height: 1px; /* The height of the black line */
  background-color: gray; /* The color of the line */
  transform: translateY(-50%);
}

.vue-splitter .splitter {
  background-color: transparent; /* Make the background transparent */
}

.vue-splitter .splitter-pane {
  overflow-y: auto;
}
</style>
